﻿
/*---------------------------------------------------------
 * Author : Tharinduni Udugamasuriya
 * Date : 30 September 2014
 * TxtMaster : Common text box for retrieve master data
 ---------------------------------------------------------*/


using DSPL.Common.ViewModel;
using DSPL.Contracts;
using DSPL.Contracts.Command;
using DSPL.Contracts.Common;
using DSPL.Contracts.Interfaces;
using Microsoft.Practices.Unity;
using System;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;


namespace DSPL.Common
{
    /// <summary>
    /// TextBox for Master Data
    /// </summary>
    public partial class TxtMaster : UserControl
    {

        public TxtMaster()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            ResolveDependancies();
        }


        #region Dependency Properties

        public static readonly DependencyProperty KeyValueProperty = DependencyProperty.Register("KeyValue", typeof(object), typeof(TxtMaster), new PropertyMetadata(null, KeyValuePropertyChangedCallback));

        public static readonly DependencyProperty KeyFieldNameProperty = DependencyProperty.Register("KeyFieldName", typeof(string), typeof(TxtMaster), new PropertyMetadata(string.Empty));

        public static readonly DependencyProperty KeyFieldTypeProperty = DependencyProperty.Register("KeyFieldType", typeof(string), typeof(TxtMaster), new PropertyMetadata(null));

        public static readonly DependencyProperty SelectedDataRowProperty = DependencyProperty.Register("SelectedDataRow", typeof(DataRow), typeof(TxtMaster), new PropertyMetadata(null, SelectedDataRowPropertyChangedCallBackEvent));

        public static readonly DependencyProperty CodeVisibilityProperty = DependencyProperty.Register("CodeVisibility", typeof(Visibility), typeof(TxtMaster), new PropertyMetadata(Visibility.Visible, CodeVisiblityPropertyChangedCallBackEvent));

        public static readonly DependencyProperty CodeEnableProperty = DependencyProperty.Register("CodeEnable", typeof(bool), typeof(TxtMaster), new PropertyMetadata(true));

        public static readonly DependencyProperty CodeEnableInnerProperty = DependencyProperty.Register("CodeEnableInner", typeof(bool), typeof(TxtMaster), new PropertyMetadata(true));

        public static readonly DependencyProperty CodeProperty = DependencyProperty.Register("Code", typeof(string), typeof(TxtMaster), new PropertyMetadata(string.Empty, CodePropertyChangedCallback));

        public static readonly DependencyProperty CodeFieldNameProperty = DependencyProperty.Register("CodeFieldName", typeof(string), typeof(TxtMaster), new PropertyMetadata(string.Empty));

        public static readonly DependencyProperty DescriptionVisibilityProperty = DependencyProperty.Register("DescriptionVisibility", typeof(Visibility), typeof(TxtMaster), new PropertyMetadata(Visibility.Visible, DescriptionVisiblityPropertyChangedCallBackEvent));

        public static readonly DependencyProperty DescriptionEnableProperty = DependencyProperty.Register("DescriptionEnable", typeof(bool), typeof(TxtMaster), new PropertyMetadata(false));

        public static readonly DependencyProperty DescriptionEnableInnerProperty = DependencyProperty.Register("DescriptionEnableInner", typeof(bool), typeof(TxtMaster), new PropertyMetadata(false));

        public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(TxtMaster), new PropertyMetadata(string.Empty));

        public static readonly DependencyProperty DescriptionFieldNameProperty = DependencyProperty.Register("DescriptionFieldName", typeof(string), typeof(TxtMaster), new PropertyMetadata(string.Empty));

        public static readonly DependencyProperty HelpNameProperty = DependencyProperty.Register("HelpName", typeof(HelpNames), typeof(TxtMaster), new PropertyMetadata(HelpNames.Default));

        public static readonly DependencyProperty AlternativeHelpNameProperty = DependencyProperty.Register("AlternativeHelpName", typeof(HelpNames), typeof(TxtMaster), new PropertyMetadata(HelpNames.Default));

        public static readonly DependencyProperty AlternativeTableNameProperty = DependencyProperty.Register("AlternativeTableName", typeof(string), typeof(TxtMaster), new PropertyMetadata(string.Empty));

        public static readonly DependencyProperty ParentFormModeProperty = DependencyProperty.Register("ParentFormMode", typeof(Modes), typeof(TxtMaster), new PropertyMetadata(Modes.Undo, ParentFormModeChangedCallBack));

        public static readonly DependencyProperty IsMandatoryProperty = DependencyProperty.Register("IsMandatory", typeof(bool), typeof(TxtMaster), new PropertyMetadata(false));

        public static readonly DependencyProperty CodeBackColorProperty = DependencyProperty.Register("CodeBackColor", typeof(Brush), typeof(TxtMaster), new PropertyMetadata(Brushes.White));

        public static readonly DependencyProperty CodeColumnSpanProperty = DependencyProperty.Register("CodeColumnSpan", typeof(int), typeof(TxtMaster), new PropertyMetadata(1));

        public static readonly DependencyProperty CodeFormatProperty = DependencyProperty.Register("CodeFormat", typeof(string), typeof(TxtMaster), new PropertyMetadata(string.Empty));

        public static readonly DependencyProperty DescriptionColumnSpanProperty = DependencyProperty.Register("DescriptionColumnSpan", typeof(int), typeof(TxtMaster), new PropertyMetadata(1));

        public static readonly DependencyProperty DescriptionColumnProperty = DependencyProperty.Register("DescriptionColumn", typeof(int), typeof(TxtMaster), new PropertyMetadata(1));

        public static readonly DependencyProperty IsFocusProperty = DependencyProperty.Register("IsFocus", typeof(bool), typeof(TxtMaster), new PropertyMetadata(false, IsFocusPropertyCahnedCallBack));

        public static readonly DependencyProperty FilterStringProperty = DependencyProperty.Register("FilterString", typeof(string), typeof(TxtMaster), new PropertyMetadata(string.Empty));
        
        #endregion

        #region Declaring Properties

        #region General Properties

        bool isInternalDataLoad;
        IMessageService MessageService;

        public HelpNames HelpName
        {
            get { return (HelpNames)GetValue(HelpNameProperty); }
            set { SetValue(HelpNameProperty, value); }
        }

        public HelpNames AlternativeHelpName
        {
            get { return (HelpNames)GetValue(AlternativeHelpNameProperty); }
            set { SetValue(AlternativeHelpNameProperty, value); }
        }

        public string AlternativeTableName
        {
            get { return (string)GetValue(AlternativeTableNameProperty); }
            set { SetValue(AlternativeTableNameProperty, value); }
        }

        public object KeyValue
        {
            get { return (object)GetValue(KeyValueProperty); }
            set { SetValue(KeyValueProperty, value); }
        }

        public string KeyFieldName
        {
            get { return (string)GetValue(KeyFieldNameProperty); }
            set { SetValue(KeyFieldNameProperty, value); }
        }

        public string KeyFieldType
        {
            get { return (string)GetValue(KeyFieldTypeProperty); }
            set { SetValue(KeyFieldTypeProperty, value); }
        }

        public DataRow SelectedDataRow
        {
            get { return (DataRow)GetValue(SelectedDataRowProperty); }
            set { SetValue(SelectedDataRowProperty, value); }
        }

        public Modes ParentFormMode
        {
            get { return (Modes)GetValue(ParentFormModeProperty); }
            set { SetValue(ParentFormModeProperty, value); }
        }

        public bool IsMandatory
        {
            get { return (bool)GetValue(IsMandatoryProperty); }
            set { SetValue(IsMandatoryProperty, value); }
        }

        public Brush CodeBackColor
        {
            get { return (Brush)GetValue(CodeBackColorProperty); }
            set { SetValue(CodeBackColorProperty, value); }
        }

        public string FilterString
        {
            get { return (string)GetValue(FilterStringProperty); }
            set { SetValue(FilterStringProperty, value); }
        }

        #endregion

        #region txtCode Properties

        public Visibility CodeVisibility
        {
            get { return (Visibility)GetValue(CodeVisibilityProperty); }
            set { SetValue(CodeVisibilityProperty, value); }
        }

        public bool CodeEnable
        {
            get { return (bool)GetValue(CodeEnableProperty); }
            set { SetValue(CodeEnableProperty, value); }
        }

        public bool CodeEnableInner
        {
            get { return (bool)GetValue(CodeEnableInnerProperty); }
            set { SetValue(CodeEnableInnerProperty, value); }
        }

        public string Code
        {
            get { return (string)GetValue(CodeProperty); }
            set { SetValue(CodeProperty, value); }
        }

        public string CodeFieldName
        {
            get { return (string)GetValue(CodeFieldNameProperty); }
            set { SetValue(CodeFieldNameProperty, value); }
        }

        public int CodeColumnSpan
        {
            get { return (int)GetValue(CodeColumnSpanProperty); }
            set { SetValue(CodeColumnSpanProperty, value); }
        }

        public string CodeFormat
        {
            get { return (string)GetValue(CodeFormatProperty); }
            set { SetValue(CodeFormatProperty, value); }
        }

        #endregion

        #region txtDescription Properties

        public Visibility DescriptionVisibility
        {
            get { return (Visibility)GetValue(DescriptionVisibilityProperty); }
            set { SetValue(DescriptionVisibilityProperty, value); }
        }

        public bool DescriptionEnable
        {
            get { return (bool)GetValue(DescriptionEnableProperty); }
            set { SetValue(DescriptionEnableProperty, value); }
        }

        public bool DescriptionEnableInner
        {
            get { return (bool)GetValue(DescriptionEnableInnerProperty); }
            set { SetValue(DescriptionEnableInnerProperty, value); }
        }

        public string Description
        {
            get { return (string)GetValue(DescriptionProperty); }
            set { SetValue(DescriptionProperty, value); }
        }

        public string DescriptionFieldName
        {
            get { return (string)GetValue(DescriptionFieldNameProperty); }
            set { SetValue(DescriptionFieldNameProperty, value); }
        }

        public int DescriptionColumnSpan
        {
            get { return (int)GetValue(DescriptionColumnSpanProperty); }
            set { SetValue(DescriptionColumnSpanProperty, value); }
        }

        public int DescriptionColumn
        {
            get { return (int)GetValue(DescriptionColumnProperty); }
            set { SetValue(DescriptionColumnProperty, value); }
        }

        public bool IsFocus
        {
            get { return (bool)GetValue(IsFocusProperty); }
            set { SetValue(IsFocusProperty, value); }
        }



        #endregion

        #endregion

        #region Property Changedback events

        private static void SelectedDataRowPropertyChangedCallBackEvent(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TxtMaster objTxtMaster = d as TxtMaster;

            if (objTxtMaster != null)
            {
                if (e.NewValue != null)
                {
                    DataRow newDataRow = e.NewValue as DataRow;
                    DataRow oldDataRow = e.OldValue as DataRow;

                    string oldKeyFiled = oldDataRow == null ? "" : oldDataRow[objTxtMaster.CodeFieldName].ToString();
                    string newKeyFiled = newDataRow[objTxtMaster.CodeFieldName].ToString();

                    if ((!oldKeyFiled.Equals(newKeyFiled)) || (objTxtMaster.Code == string.Empty))
                        objTxtMaster.FillData();
                    //if (!e.NewValue.Equals(e.OldValue))
                    //    objTxtMaster.FillData();
                }
                else
                    objTxtMaster.ClearControls();
            }
        }

        private static void ParentFormModeChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TxtMaster objTxtMaster = d as TxtMaster;

            if (objTxtMaster != null)
            {
                Modes newMode = (Modes)e.NewValue;
                objTxtMaster.EnableDisableControls(newMode);
            }
        }

        private static void KeyValuePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TxtMaster objTxtMaster = d as TxtMaster;

            if (objTxtMaster != null && !objTxtMaster.isInternalDataLoad)
            {
                if (e.NewValue != null)
                {
                    if (!e.NewValue.Equals(e.OldValue))
                        objTxtMaster.RefreshDatabyKey();
                }
                else
                    objTxtMaster.ClearControls();
            }
        }

        private static void CodePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TxtMaster objTxtMaster = d as TxtMaster;

            if (objTxtMaster != null && !objTxtMaster.isInternalDataLoad)
            {
                if (e.NewValue != null)
                {
                    if (!e.NewValue.Equals(e.OldValue))
                    {
                        objTxtMaster.RefreshDatabyCode(QComparison.EQUALS);                       
                    }
                }
                else
                    objTxtMaster.ClearControls();

                objTxtMaster.ChangeBackColor();
            }

        }

        private static void CodeVisiblityPropertyChangedCallBackEvent(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TxtMaster objTxtMaster = d as TxtMaster;

            if (objTxtMaster != null)
            {
                if (e.NewValue.Equals(Visibility.Collapsed) || e.NewValue.Equals(Visibility.Hidden))
                {
                    objTxtMaster.DescriptionColumn = 0;
                    objTxtMaster.DescriptionColumnSpan = 2;
                }
                else
                {
                    objTxtMaster.DescriptionColumn = 1;
                    objTxtMaster.DescriptionColumnSpan = 1;
                }
            }
        }

        private static void DescriptionVisiblityPropertyChangedCallBackEvent(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TxtMaster objTxtMaster = d as TxtMaster;

            if (objTxtMaster != null)
            {
                if (e.NewValue.Equals(Visibility.Collapsed) || e.NewValue.Equals(Visibility.Hidden))
                    objTxtMaster.CodeColumnSpan = 2;
                else
                    objTxtMaster.CodeColumnSpan = 1;
            }
        }

        private static void IsFocusPropertyCahnedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TxtMaster objTxtMaster = d as TxtMaster;

            if (objTxtMaster != null)
            {
                if (e.NewValue.Equals(true))
                    objTxtMaster.FocusChangeEvent();
            }
        }

        #endregion

        #region Exposable Events

        public event EventHandler<EventArgs> RefreshAttachedObjects;

        #endregion

        #region Internal events

        private void FocusChangeEvent()
        {
            txtCode.Focus();
            IsFocus = false;
        }

        private void ChangeBackColor()
        {
            CodeBackColor = Brushes.White;
            if (IsMandatory && string.IsNullOrEmpty(Code))
                CodeBackColor = Brushes.LavenderBlush;
        }

        public virtual void ClearControls()
        {
            KeyValue = null;
            Code = "";
            Description = "";
            SelectedDataRow = null;
        }

        public virtual void FillData()
        {
            isInternalDataLoad = true;

            KeyValue = SelectedDataRow[KeyFieldName];
            Code = SelectedDataRow[CodeFieldName] == null ? "" : (string)SelectedDataRow[CodeFieldName];
            Description = SelectedDataRow[DescriptionFieldName] == null ? "" : (string)SelectedDataRow[DescriptionFieldName];
            if (RefreshAttachedObjects != null)
                RefreshAttachedObjects(this, new EventArgs());                      //use to display data in attached properites

            isInternalDataLoad = false;
        }

        private void RefreshDatabyKey()
        {
            if (KeyValue != null && !string.IsNullOrEmpty(KeyValue.ToString()))
                RefreshData(KeyFieldName, KeyValue, KeyFieldType.ToUpper());
            else
                ClearControls();
        }

        private void RefreshDatabyCode(QComparison filterEquation)
        {
            if (!string.IsNullOrEmpty(Code))
                RefreshData(CodeFieldName, Code, "STRING", filterEquation);
            else
                ClearControls();
        }


        private void RefreshData(string filterColumn, object filterValue, string filterType, QComparison filterEquation = QComparison.EQUALS)
        {
            if (!string.IsNullOrEmpty(filterColumn) && filterValue != null && !string.IsNullOrEmpty(filterValue.ToString()))
            {
                ListWindowViewModel vmListWindow = new ListWindowViewModel();
                if (vmListWindow != null)
                {
                    vmListWindow.HelpName = this.HelpName;
                    vmListWindow.FilterColumn = filterColumn;
                    vmListWindow.FilterValue = filterValue;
                    vmListWindow.FilterType = filterType;
                    vmListWindow.FilterEquation = filterEquation;
                    vmListWindow.AlternativeHelpName = this.AlternativeHelpName;
                    vmListWindow.AlternativeTableName = this.AlternativeTableName;
                    vmListWindow.FormMode = ParentFormMode;
                    vmListWindow.FilterString = FilterString;
                    vmListWindow.Initialize();

                    if (vmListWindow.RowCount > 1 && KeyValue == null)
                        MessageService.ShowPopupWindow(vmListWindow);

                    if (vmListWindow.SelectedRow != null)
                        SelectedDataRow = vmListWindow.SelectedRow;

                    if (vmListWindow.RowCount == 0)
                    {
                        ClearControls();
                        IsFocus = true;
                    }


                }
            }
            else
                ClearControls();
        }

        private void ResolveDependancies()
        {
            IUnityContainer container = GlobalVariables.GlobalUnityContainer;
            if (container != null)
            {
                MessageService = container.Resolve<IMessageService>();
            }
        }

        private void LoadHelp()
        {
            ListWindowViewModel vmListWindow = new ListWindowViewModel();
            if (vmListWindow != null)
            {
                vmListWindow.HelpName = this.HelpName;
                vmListWindow.FilterString = FilterString;
                vmListWindow.Initialize();
                MessageService.ShowPopupWindow(vmListWindow);
                if (vmListWindow.SelectedRow != null)
                    SelectedDataRow = vmListWindow.SelectedRow;
                //else
                //    ClearControls();
            }
        }

        private void EnableDisableControls(Modes newMode)
        {
            switch (newMode)
            {
                case Modes.New:
                case Modes.Edit:
                    CodeEnableInner = CodeEnable;
                    DescriptionEnableInner = DescriptionEnable;
                    break;

                case Modes.None:
                case Modes.Delete:
                case Modes.Approve:
                case Modes.Print:
                case Modes.Save:
                case Modes.Undo:
                case Modes.First:
                case Modes.Previous:
                case Modes.Next:
                case Modes.Last:
                    CodeEnableInner = false;
                    DescriptionEnableInner = false;
                    break;

            }
        }

        #endregion

        #region Control's inbuilt events

        private void CodeDoubleClick(object sender, MouseButtonEventArgs e)
        {
            LoadHelp();
        }

        private void CodeKeyPress(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.F1)
                LoadHelp();
            else if (e.Key == Key.Enter || e.Key == Key.Return)
                RefreshDatabyCode(QComparison.LIKE);
        }

        #endregion
        
    }
}
